package com.yugao.fintech.antelope.pay.payment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yugao.fintech.antelope.pay.common.assembly.PayOrderAssembly;
import com.yugao.fintech.antelope.pay.common.assembly.RefundAssembly;
import com.yugao.fintech.antelope.pay.common.manager.PayMqSender;
import com.yugao.fintech.antelope.pay.common.model.mq.MchNotifyMQ;
import com.yugao.fintech.antelope.pay.common.service.MchNotifyRecordService;
import com.yugao.fintech.antelope.pay.model.entity.MchNotifyRecord;
import com.yugao.fintech.antelope.pay.model.entity.PayOrder;
import com.yugao.fintech.antelope.pay.model.entity.RefundOrder;
import com.yugao.fintech.antelope.pay.model.entity.TransferOrder;
import com.yugao.fintech.antelope.pay.model.rqrs.pay.payorder.PayOrderNotify;
import com.yugao.fintech.antelope.pay.model.rqrs.pay.refund.RefundOrderNotify;
import com.yugao.fintech.antelope.pay.payment.model.rqrs.transfer.QueryTransferOrderRS;
import com.yugao.fintech.antelope.pay.payment.service.ConfigContextQueryService;
import com.yugao.fintech.antelope.pay.payment.service.PayMchNotifyService;
import com.yugao.fintech.antelope.system.SystemApi;
import com.yugao.fintech.antelope.system.model.rqrs.accesskey.AccessKeyResp;
import com.yugao.fintech.framework.assistant.utils.StringUtils;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.assistant.sign.SignPayload;
import com.yugao.fintech.framework.assistant.sign.SignType;
import com.yugao.fintech.framework.assistant.sign.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Slf4j
@Service
public class PayMchNotifyServiceImpl implements PayMchNotifyService {
    @Autowired
    private MchNotifyRecordService mchNotifyRecordService;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private PayMqSender payMqSender;

    @Autowired
    private PayOrderAssembly payOrderAssembly;

    @Autowired
    private RefundAssembly refundAssembly;

    @Autowired
    private SystemApi systemApi;

    @Override
    public void payOrderNotify(PayOrder dbPayOrder) {
        try {
            // 通知地址为空
            if(StringUtils.isEmpty(dbPayOrder.getNotifyUrl())){
                return ;
            }

            // 获取到通知对象
            MchNotifyRecord mchNotifyRecord = mchNotifyRecordService.getByPayOrder(dbPayOrder.getPayOrderNo());

            if(mchNotifyRecord != null){
                log.info("当前已存在通知消息， 不再发送。");
                return ;
            }

            // 商户app私钥
            String accessKeyId = configContextQueryService.queryMchApp(dbPayOrder.getMchNo(), dbPayOrder.getAppId()).getAccessKeyId();

            // 封装通知url
            String notifyUrl = createNotifyUrl(dbPayOrder, accessKeyId);
            mchNotifyRecord = new MchNotifyRecord();
            mchNotifyRecord.setOrderNo(dbPayOrder.getPayOrderNo());
            mchNotifyRecord.setOrderType(MchNotifyRecord.TYPE_PAY_ORDER);
            mchNotifyRecord.setMchNo(dbPayOrder.getMchNo());
            mchNotifyRecord.setMchOrderNo(dbPayOrder.getMchOrderNo()); //商户订单号
            mchNotifyRecord.setIsvNo(dbPayOrder.getIsvNo());
            mchNotifyRecord.setAppId(dbPayOrder.getAppId());
            mchNotifyRecord.setNotifyUrl(notifyUrl);
            mchNotifyRecord.setResResult("");
            mchNotifyRecord.setNotifyCount(0);
            mchNotifyRecord.setStatus(MchNotifyRecord.STATE_ING); // 通知中

            if (mchNotifyRecordService.isExistMchNotifyRecord(dbPayOrder.getId(), MchNotifyRecord.TYPE_PAY_ORDER)) {
                log.info("数据库已存在[{}]消息，本次不再推送。", mchNotifyRecord.getOrderNo());
                return ;
            }

            try {
                mchNotifyRecordService.save(mchNotifyRecord);
            } catch (Exception e) {
                return ;
            }

            // 推送到MQ
            Long notifyId = mchNotifyRecord.getId();
            payMqSender.sendDelay(MchNotifyMQ.build(notifyId), 1);
        } catch (Exception e) {
            log.error("推送失败！", e);
        }
    }

    @Override
    public void refundOrderNotify(RefundOrder refundOrder) {
        try {
            // 通知地址为空
            if(StringUtils.isEmpty(refundOrder.getNotifyUrl())){
                return ;
            }

            //获取到通知对象
            MchNotifyRecord mchNotifyRecord = mchNotifyRecordService.getByRefundOrder(refundOrder.getRefundOrderId());

            if(mchNotifyRecord != null){
                log.info("当前已存在通知消息， 不再发送。");
                return ;
            }

            //商户app私钥
            String accessKeyId = configContextQueryService.queryMchApp(refundOrder.getMchNo(), refundOrder.getAppId()).getAccessKeyId();

            // 封装通知url
            String notifyUrl = createNotifyUrl(refundOrder, accessKeyId);
            mchNotifyRecord = new MchNotifyRecord();
            mchNotifyRecord.setOrderNo(refundOrder.getRefundOrderId());
            mchNotifyRecord.setOrderType(MchNotifyRecord.TYPE_REFUND_ORDER);
            mchNotifyRecord.setMchNo(refundOrder.getMchNo());
            mchNotifyRecord.setMchOrderNo(refundOrder.getMchRefundNo()); //商户订单号
            mchNotifyRecord.setIsvNo(refundOrder.getIsvNo());
            mchNotifyRecord.setAppId(refundOrder.getAppId());
            mchNotifyRecord.setNotifyUrl(notifyUrl);
            mchNotifyRecord.setResResult("");
            mchNotifyRecord.setNotifyCount(0);
            mchNotifyRecord.setStatus(MchNotifyRecord.STATE_ING); // 通知中

            if (mchNotifyRecordService.isExistMchNotifyRecord(refundOrder.getRefundOrderId(), MchNotifyRecord.TYPE_REFUND_ORDER)) {
                log.info("数据库已存在[{}]消息，本次不再推送。", mchNotifyRecord.getOrderNo());
                return ;
            }
            try {
                mchNotifyRecordService.save(mchNotifyRecord);
            } catch (Exception e) {
                return ;
            }

            // 推送到MQ
            Long notifyId = mchNotifyRecord.getId();
            payMqSender.sendDelay(MchNotifyMQ.build(notifyId), 1);
        } catch (Exception e) {
            log.error("推送失败！", e);
        }
    }

    @Override
    public void transferOrderNotify(TransferOrder dbTransferOrder) {
        try {
            // 通知地址为空
            if(StringUtils.isEmpty(dbTransferOrder.getNotifyUrl())){
                return ;
            }

            // 获取到通知对象
            MchNotifyRecord mchNotifyRecord = mchNotifyRecordService.getByTransferOrder(dbTransferOrder.getTransferNo());

            if(mchNotifyRecord != null){
                log.info("当前已存在通知消息， 不再发送。");
                return ;
            }

            // 商户app私钥
            String accessKeyId = configContextQueryService.queryMchApp(dbTransferOrder.getMchNo(), dbTransferOrder.getAppId()).getAccessKeyId();

            // 封装通知url
            String notifyUrl = createNotifyUrl(dbTransferOrder, accessKeyId);
            mchNotifyRecord = new MchNotifyRecord();
            mchNotifyRecord.setOrderNo(dbTransferOrder.getTransferNo());
            mchNotifyRecord.setOrderType(MchNotifyRecord.TYPE_TRANSFER_ORDER);
            mchNotifyRecord.setMchNo(dbTransferOrder.getMchNo());
            mchNotifyRecord.setMchOrderNo(dbTransferOrder.getMchOrderNo()); //商户订单号
            mchNotifyRecord.setIsvNo(dbTransferOrder.getIsvNo());
            mchNotifyRecord.setAppId(dbTransferOrder.getAppId());
            mchNotifyRecord.setNotifyUrl(notifyUrl);
            mchNotifyRecord.setResResult("");
            mchNotifyRecord.setNotifyCount(0);
            mchNotifyRecord.setStatus(MchNotifyRecord.STATE_ING); // 通知中

            if (mchNotifyRecordService.isExistMchNotifyRecord(dbTransferOrder.getTransferNo(), MchNotifyRecord.TYPE_TRANSFER_ORDER)) {
                log.info("数据库已存在[{}]消息，本次不再推送。", mchNotifyRecord.getOrderNo());
                return ;
            }

            try {
                mchNotifyRecordService.save(mchNotifyRecord);
            } catch (Exception e) {
                return ;
            }

            //推送到MQ
            Long notifyId = mchNotifyRecord.getId();
            payMqSender.sendDelay(MchNotifyMQ.build(notifyId), 1);

        } catch (Exception e) {
            log.error("推送失败！", e);
        }
    }

    @Override
    public String createNotifyUrl(PayOrder payOrder, String accessKeyId) throws Exception {
        AccessKeyResp accessKeyResp = systemApi.getAccessKeyById(Long.valueOf(accessKeyId));
        if (Objects.isNull(accessKeyResp)) {
            throw new BizException("accessKeyId={} 不存在", accessKeyId);
        }

        PayOrderNotify payOrderNotify = payOrderAssembly.toPayOrderNotify(payOrder);
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(payOrderNotify);

        SignPayload signPayload = SignUtils.genSign(SignType.MD5, accessKeyResp.getSecretId(), accessKeyResp.getSecretKey(), jsonObject);
        jsonObject.putAll(signPayload.toMapOfObjectType());

        // 生成通知
        return StringUtils.appendUrlQuery(payOrder.getNotifyUrl(), jsonObject);
    }

    @Override
    public String createNotifyUrl(RefundOrder refundOrder, String accessKeyId) throws Exception {
        AccessKeyResp accessKeyResp = systemApi.getAccessKeyById(Long.valueOf(accessKeyId));
        RefundOrderNotify refundOrderNotify = refundAssembly.toRefundOrderNotify(refundOrder);
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(refundOrderNotify);
        SignPayload signPayload = SignUtils.genSign(SignType.MD5, accessKeyResp.getSecretId(), accessKeyResp.getSecretKey(), jsonObject);
        jsonObject.putAll(signPayload.toMapOfObjectType());
        // 生成通知
        return StringUtils.appendUrlQuery(refundOrder.getNotifyUrl(), jsonObject);
    }

    @Override
    public String createNotifyUrl(TransferOrder transferOrder, String accessKeyId) throws Exception {
        AccessKeyResp accessKeyResp = systemApi.getAccessKeyById(Long.valueOf(accessKeyId));
        QueryTransferOrderRS rs = QueryTransferOrderRS.buildByRecord(transferOrder);
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(rs);
        SignPayload signPayload = SignUtils.genSign(SignType.MD5, accessKeyResp.getSecretId(), accessKeyResp.getSecretKey(), jsonObject);
        jsonObject.putAll(signPayload.toMapOfObjectType());
        // 生成通知
        return StringUtils.appendUrlQuery(transferOrder.getNotifyUrl(), jsonObject);
    }

    @Override
    public String createReturnUrl(PayOrder payOrder, String accessKeyId) throws Exception {
        if(StringUtils.isEmpty(payOrder.getReturnUrl())){
            return "";
        }
        AccessKeyResp accessKeyResp = systemApi.getAccessKeyById(Long.valueOf(accessKeyId));

        PayOrderNotify payOrderNotify = payOrderAssembly.toPayOrderNotify(payOrder);
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(payOrderNotify);

        SignPayload signPayload = SignUtils.genSign(SignType.MD5, accessKeyResp.getSecretId(), accessKeyResp.getSecretKey(), jsonObject);
        jsonObject.putAll(signPayload.toMapOfObjectType());

        // 生成跳转地址
        return StringUtils.appendUrlQuery(payOrder.getReturnUrl(), jsonObject);
    }
}
